#!/bin/sh

#作者：高伟
#my email: xiyou.gaowei@gmail.com
#version: G_IPv6P 0.1

version=1
#用法说明
usage()
{
echo 
echo "Today's date is `date`"
echo "The software's usage,非随机产生器用法如下"
echo "./G"$version"_IPv6P -h|fa|ff -A|B -a|d|o"
echo "第一个参数是fa时是选择一个固定的IPv4前缀并且进行自动扩展"
echo "第一个参数是ff时是从文件中读取IPv4的前缀"
echo "第一个参数为-h时获得帮助文件"
echo
echo "首选为B选项"
echo "第二个参数是A是采用非随机产生的A策略"
echo "第二个参数是B是采用非随机产生的B策略"
echo
echo "当采用B策略时第三个参数才有用,A策略不需要第三个参数"
echo "第三个参数是a时是产生所有的ASN值"
echo "第三个参数是d时是几个固定的常用的ASN的值"
echo "第三个参数是o时是给定一个ASN的值"
echo
}
#判断参数
if [ "$1" = "-fa" ] || [ "$1" = "-ff" ] || [ "$1" = "-h" ]; then
	case "$1" in
        	-fa) echo -n "固定的IPv4前缀并且进行扩展, ";;
		-ff) echo -n "从文件中读IPv4前缀的值, ";;
		* | h* | H*)    usage;;
	esac
#判断第二个参数
	if [ "$2" = "-A" ] || [ "$2" = "-B" ]; then
		case "$2" in
			-A) echo "用A策略产生IPv6前缀";;
			-B) echo -n "用B策略产生IPv6前缀"
#判断第三个参数
			if [ "$3" = "-a" ] || [ "$3" = "-d" ] || [ "$3" = "-o" ]; then
				case "$3" in
					-a) echo "产生所有的ASN值, ";;
					-d) echo "是随机产生几个ASN的值, ";;
				-o) echo "给定一个ASN的值, ";;
			*) usage;;
				esac
			else
				usage
				echo "第三个参数错误"
			fi
			;;
			*) usage;;
		esac
	else
		if [ "$1" != "-h" ]; then
			usage
			echo "请正确输入第二个参数"
		fi
	fi
else
	usage
	echo "第一个参数错误"
fi


#输入IPv4前缀
read_IPv4P()
{
echo "请输入一个IPv4前缀，如202.117.128.0/20"
read IPv4P
}

#对IPv4前缀进行处理
#第一步分割十进制的ip
cut_IPv4P()
{
#把IPv4前缀分割成5个部分
ip1=`echo "$IPv4P" | cut -f 1 -d "."`
ip2=`echo "$IPv4P" | cut -f 2 -d "."`
ip3=`echo "$IPv4P" | cut -f 3 -d "."`
ip5=`echo "$IPv4P" | cut -f 4 -d "."`
ip4=`echo "$ip5" | cut -f 1 -d "/"`
IPv4L=`echo "$ip5" | cut -f 2 -d "/"`
#限定IPv4L的范围
if [ "$IPv4L" -lt "8" ] || [ "$IPv4L" -gt "32" ];then
	echo "IPv4前缀长度不对请重新输入"
	read_IPv4P
	cut_IPv4P
fi
#把上面的5个部分，从10进制转化为2进制
IP1=`echo "obase=2; ibase=10; $ip1"|bc`
IP2=`echo "obase=2; ibase=10; $ip2"|bc`
IP3=`echo "obase=2; ibase=10; $ip3"|bc`
IP4=`echo "obase=2; ibase=10; $ip4"|bc`
#一个数组进行保存上面的数据，一个数组保存改变后的数组
P=($IP1 $IP2 $IP3 $IP4)
p=(i1 i2 i3 i4)
#把IPv4前缀转换为一个2进制的字符串
for ((i=0;i<4;i++));do
        l=${#P[i]}
        if [ "$l" -le "8" ]; then
                zr_number=`expr 8 - $l`
                a=${P[i]}
                while [ "$zr_number" -gt "0" ]; do
                        a=0$a
                        zr_number=`expr $zr_number - 1`
                done
        fi
        p[i]=$a
done

i1=`echo "${p[0]}"`
i2=`echo "${p[1]}"`
i3=`echo "${p[2]}"`
i4=`echo "${p[3]}"`
IPv4PT=`echo "$i1$i2$i3$i4"`
}

#第二步进行处理
change_IPv4P()
{
IPt1=`echo $IPv4PT|awk '{print substr($IPv4PT,1,8)}'`
IPt2=`echo $IPv4PT|awk '{print substr($IPv4PT,9,8)}'`
IPt3=`echo $IPv4PT|awk '{print substr($IPv4PT,17,8)}'`
IPt4=`echo $IPv4PT|awk '{print substr($IPv4PT,25,8)}'`

#把IPv4前缀转换成俩组16进制的数
IPv4P11=`echo $IPt1|awk '{print substr($IPt1,1,4)}'`
IPv4P12=`echo $IPt1|awk '{print substr($IPt1,5,4)}'`
IPv4O11=`echo "obase=16; ibase=2; $IPv4P11"|bc`
IPv4O12=`echo "obase=16; ibase=2; $IPv4P12"|bc`

IPv4P21=`echo $IPt2|awk '{print substr($IPt2,1,4)}'`
IPv4P22=`echo $IPt2|awk '{print substr($IPt2,5,4)}'`
IPv4O21=`echo "obase=16; ibase=2; $IPv4P21"|bc`
IPv4O22=`echo "obase=16; ibase=2; $IPv4P22"|bc`

IPv4P31=`echo $IPt3|awk '{print substr($IPt3,1,4)}'`
IPv4P32=`echo $IPt3|awk '{print substr($IPt3,5,4)}'`
IPv4O31=`echo "obase=16; ibase=2; $IPv4P31"|bc`
IPv4O32=`echo "obase=16; ibase=2; $IPv4P32"|bc`

IPv4P41=`echo $IPt4|awk '{print substr($IPt4,1,4)}'`
IPv4P42=`echo $IPt4|awk '{print substr($IPt4,5,4)}'`
IPv4O41=`echo "obase=16; ibase=2; $IPv4P41"|bc`
IPv4O42=`echo "obase=16; ibase=2; $IPv4P42"|bc`

IPv6P1=`echo "$IPv4O11$IPv4O12$IPv4O21$IPv4O22"`
IPv6P2=`echo "$IPv4O31$IPv4O32$IPv4O41$IPv4O42"`
IPv4_prefix=`echo "$IPv6P1:$IPv6P2"`
}

#对IPv4前缀的固定值进行扩展
IPv4Pfa()
{
T_IPv4P=`echo "$i1$i2$i3$i4"`
L_IPv4P=`echo $T_IPv4P|awk '{print substr($T_IPv4P,1,PL)}' PL=$IPv4L`
let "sus=2**$IPv4L"
O_IPv4P=`echo "obase=10; ibase=2; $L_IPv4P"|bc`
}
#功能是上面的继续，分开也许更好些
aIPv4Pfa()
{
f=0
while [ "$f" = "0" ]; do
	IPv6P=`echo "$asn:$IPv4_prefix:$rrandom/$IPv6L"`
	IPv6_address
	echo "$IPv6P"	
	#echo "$asn:$IPv4_prefix:$rrandom/$IPv6L" >> IPv6_Prefix_Btable
	if [ "$IPv6_Prefix_Btable" != "no" ]; then
		echo "$IPv6P" >> $IPv6_Prefix_Btable
	fi
	if [ "$O_IPv4P" -lt "$sus" ]; then
		O_IPv4P=`expr $O_IPv4P + 1`
		four=`expr $O_IPv4P % 4`
		if [ "$four" -eq "0" ]; then
			af=(0 1)
			Raf=`echo -n ${af[$RANDOM % ${#af[*]}]}`
			if [ "$Raf" -eq "1" ]; then
				IPv6L=`expr $IPv6L - 1`
			else
				IPv6L=`expr $IPv6L + 1`
			fi
		else 
			range
		fi
		Ta_IPv4P=`echo "obase=2; $O_IPv4P" | bc`
		patch_OIPv4P
		change_IPv4P
	else
		f=1
	fi
done
}

#对转换成为十进制的IPv4前缀进行转换
patch_OIPv4P()
{
Ta_IPv4PL=`echo $Ta_IPv4P|awk '{print length($Ta_IPv4P)}'`
if [ "$Ta_IPv4PL" -le "32" ]; then
	O_number=`expr 32 - $Ta_IPv4PL`
	Oa=$Ta_IPv4P
	while [ "$O_number" -gt "0" ]; do
		Oa=$Oa"0"
		O_number=`expr $O_number - 1`
	done
fi
IPv4PT=$Oa
}

#从文件中读IPv4前缀的值
IPv4Pff()
{
echo "请输入要读取的文件名"
fflag=0
while [ "$fflag" -eq "0" ]; do
	read ffilename
	if [ -f "$ffilename" ]; then
		fflag=1
		filename_number=`wc $ffilename`
		number=`echo $filename_number|awk '{print $1}'`
		echo "输入需要的读多少行i,如果要全部输入则输入a"
		read inumber
		if [ "$inumber" = "a" ]; then
			inumber=$number
		else
			inumber=$inumber
		fi
		if [ "$inumber" -gt "$number" ]; then
			echo "$i数字大于文件行数,重新输入"
			IPv4Pff
		fi
	else
		echo "文件不存在，请重新输入"
		fflag=0
	fi
done
}

#产生全部的asn
asna()
{
#实现asn的值
s=$asna
asna_i=`echo "obase=2; $asna" | bc`
asna_iL=`echo $asna_i|awk '{print length($asna_i)}'`
        if [ "$asna_iL" -lt "16" ]
        then
                az_number=`expr 16 - $asna_iL`
                asna_j=$asna_i
                while [ "$az_number" -gt "0" ]; do
                        asna_j=0$asna_j
                        az_number=`expr $az_number - 1`
                done
        fi
asna_jL=`echo $asna_j|awk '{print length($asna_j)}'`
L1=`echo $asna_j|awk '{print substr($asna_j,1,4)}'`
L2=`echo $asna_j|awk '{print substr($asna_j,5,4)}'`
L3=`echo $asna_j|awk '{print substr($asna_j,9,4)}'`
L4=`echo $asna_j|awk '{print substr($asna_j,13,4)}'`
l1=`echo "obase=16; ibase=2; $L1"|bc`
l2=`echo "obase=16; ibase=2; $L2"|bc`
l3=`echo "obase=16; ibase=2; $L3"|bc`
l4=`echo "obase=16; ibase=2; $L4"|bc`
ASN=`echo "$l1$l2$l3$l4"`
}

#默认的asn
asnd()
{
asnd=(3FFE 2001 2002)
}

#给定一个asn
asno()
{
echo "请输入一个固定的asn"
echo "常用的几个值3FFE, 2002和2001"
read asno
}

#确定IPv6前缀的长度
range()
{
if [ "$IPv4L" -eq "8" ]; then
	IPv6L=23
else
	IPv6L=`expr $IPv4L "*" 2`
fi
}

#判断是否需要随机值
whether_random()
{
if [ "$IPv6L" -gt "48" ]; then
        randomL=`expr $IPv6L - 48`
	if [ "$random" = "0" ]; then
	        echo "自动或手动输入一个 $randomL bit的随机值，自动则输入a即可"
        	read random
	fi
        #生成一个随机数
        if [ "$random" = "a" ]; then
                flag=r
                r_a=(0 1)
                random=`for ((i=0;i<$randomL;i++)); do echo -n ${r_a[$RANDOM % ${#r_a[*]}]}; done`
        else
                flag=r
        fi
fi

#判断是否输出随机数
if [ "$flag" = "r" ]; then
        ran=$random
        if [ "$randomL" -lt "16" ]
        then
                rz_number=`expr 16 - $randomL`
                while [ "$rz_number" -gt "0" ]; do
                        ran=$ran"0"
                        rz_number=`expr $rz_number - 1`
                done
        fi
        random1=`echo $ran|awk '{print substr($ran,1,4)}'`
        random2=`echo $ran|awk '{print substr($ran,5,4)}'`
        random3=`echo $ran|awk '{print substr($ran,9,4)}'`
        random4=`echo $ran|awk '{print substr($ran,13,4)}'`
#把随机数转换成16进制的
        orandom1=`echo "obase=16; ibase=2; $random1"|bc`
        orandom2=`echo "obase=16; ibase=2; $random2"|bc`
        orandom3=`echo "obase=16; ibase=2; $random3"|bc`
        orandom4=`echo "obase=16; ibase=2; $random4"|bc`

        orandom=`echo "$orandom1$orandom2$orandom3$orandom4"`
        rrandom=`echo "$orandom"`
else
        zero=0000
        rrandom=`echo "$zero"`
fi
}

#创建文件将用于保存输出结果
save_date_to_file()
{
echo "把数据输入一个文件，请写一个文件名，如果不想输入到文件则输入no"
read IPv6_Prefix_Btable
if [ "$IPv6_Prefix_Btable" != "no" ]; then
	if [ -e $IPv6_Prefix_Btable ]; then
		echo "已经有$IPv6_Prefix_Btable"
	        echo "是否删除原来的$IPv6_Prefix_Btable，yes或者no"
	        read y_or_n
        	case "$y_or_n" in
	                y*) rm $IPv6_Prefix_Btable
        	            echo "已经删除原来$IPv6_Prefix_Btable创建了新的";;
        	        n*) echo "原来文件没有被删除";;
		esac
	else
        	touch $IPv6_Prefix_Btable
	fi
fi
}

#按照IPv6地址规则输出
IPv6_address()
{
#IPv6P=`echo "$asn:$IPv4_prefix:$rrandom/$IPv6L"`
IPv6Pa=`echo "$IPv6P" | cut -f 1 -d "/"`
IPv6Pa1=`echo "$IPv6Pa" | cut -f 1 -d ":"`
IPv6Pa2=`echo "$IPv6Pa" | cut -f 2 -d ":"`
IPv6Pa3=`echo "$IPv6Pa" | cut -f 3 -d ":"`
IPv6Pa4=`echo "$IPv6Pa" | cut -f 4 -d ":"`
#IPv6a1,在此次算法中不可以为0，所以不作判断
if [ "$IPv6Pa2" = "0000" ] && [ "$IPv6Pa3" = "0000" ] && [ "$IPv6Pa4" = "0000" ]; then
        IPv6P=`echo "$IPv6Pa1::/$IPv6L"`
fi
if [ "$IPv6Pa2" = "0000" ] && [ "$IPv6Pa3" = "0000" ] && [ "$IPv6Pa4" != "0000" ]; then
        IPv6P=`echo "$IPv6Pa1::$IPv6Pa4/$IPv6L"`
fi
if [ "$IPv6Pa2" != "0000" ] && [ "$IPv6Pa3" = "0000" ] && [ "$IPv6Pa4" = "0000" ]; then
        IPv6P=`echo "$IPv6Pa1:$IPv6Pa2::/$IPv6L"`
fi
if [ "$IPv6Pa2" != "0000" ] && [ "$IPv6Pa3" != "0000" ] && [ "$IPv6Pa4" = "0000" ]; then
	IPv6P=`echo "$IPv6Pa1:$IPv6Pa2:$IPv6Pa3::/$IPv6L"`
fi
if [ "$IPv6Pa2" != "0000" ] && [ "$IPv6Pa3" != "0000" ] && [ "$IPv6Pa4" != "0000" ]
	then
	IPv6P=`echo "$IPv6Pa1:$IPv6Pa2:$IPv6Pa3:$IPv6Pa4::/$IPv6L"`
fi
}

#第一个参数时都要用到
fa_ado()
{
#读前缀，改变前缀
read_IPv4P
cut_IPv4P
change_IPv4P
range
random=0
whether_random
#对IPv4P进行扩展
IPv4Pfa
save_date_to_file
}

#如果参数为fa和a时
if [ "$1" = "-fa" ] && [ "$3" = "-a" ] && [ "$2" = "-B" ]; then
fa_ado
asna=`expr 1024 "*" 16 - 1`
while [ "$asna" -ge "0" ]; do
	asna
	asn=$ASN
	aIPv4Pfa
	asna=`expr $s - 1`
done
fi

#如果参数为fa和d时
if [ "$1" = "-fa" ] && [ "$3" = "-d" ] && [ "$2" = "-B" ]; then
fa_ado
	for ((fan=0;fan<3;fan++));do
		asnd
		asn=${asnd[fan]}
		aIPv4Pfa
	done
fi

#如果参数为fa和o时
if [ "$1" = "-fa" ] && [ "$3" = "-o" ] && [ "$2" = "-B" ]; then
#获得一个固定的asn
asno
asn=$asno
fa_ado
aIPv4Pfa
fi

#遍历文件中要读取的IPv4的前缀
traversal()
{
for((f_j=1;f_j<=$inumber;f_j++));do
	IPv4P=`awk '{if (NR==f_m) print $1}' f_m=$f_j $ffilename`
	cut_IPv4P
	change_IPv4P
	random=a
	whether_random
	IPv6P=`echo "$asn:$IPv4_prefix:$rrandom/$IPv6L"`
	IPv6_address
	echo "$IPv6P"
	if [ "$IPv6_Prefix_Btable" != "no" ]; then
		echo "$IPv6P" >> $IPv6_Prefix_Btable	
	fi
done	
}

#如果参数为ff和a时
if [ "$1" = "-ff" ] && [ "$3" = "-a" ] && [ "$2" = "-B" ]; then
IPv4Pff
save_date_to_file
asna=`expr 1024 "*" 16 - 1`
while [ "$asna" -ge "0" ]; do
        asna
        asn=$ASN
	traversal
        asna=`expr $s - 1`
done
fi

#如果参数为ff和d时
if [ "$1" = "-ff" ] && [ "$3" = "-d" ] && [ "$2" = "-B" ]; then
IPv4Pff
save_date_to_file
ffn=0
	while [ "$ffn" -lt "3" ]; do
		asnd
		asn=${asnd[ffn]}
		traversal
		ffn=`expr $ffn + 1`
	done
fi

#如果参数为ff和o时
if [ "$1" = "-ff" ] && [ "$3" = "-o" ] && [ "$2" = "-B" ]; then
IPv4Pff	
asno
asn=$asno
save_date_to_file
traversal
fi

#下面是A组策略
g_change()
{
gp1=`echo $g_prefix|awk '{print substr($g_prefix,1,16)}'`
gp2=`echo $g_prefix|awk '{print substr($g_prefix,17,16)}'`
gp3=`echo $g_prefix|awk '{print substr($g_prefix,33,16)}'`
gp4=`echo $g_prefix|awk '{print substr($g_prefix,49,16)}'`
gp=($gp1 $gp2 $gp3 $gp4)
for ((i=0;i<4;i++));do
	ap=${gp[i]}
	gL1=`echo $ap|awk '{print substr($ap,1,4)}'`
	gL2=`echo $ap|awk '{print substr($ap,5,4)}'`
	gL3=`echo $ap|awk '{print substr($ap,9,4)}'`
	gL4=`echo $ap|awk '{print substr($ap,13,4)}'`
	gl1=`echo "obase=16; ibase=2; $gL1"|bc`
	gl2=`echo "obase=16; ibase=2; $gL2"|bc`
	gl3=`echo "obase=16; ibase=2; $gL3"|bc`
	gl4=`echo "obase=16; ibase=2; $gL4"|bc`
	gpf=`echo "$gl1$gl2$gl3$gl4"`
	pg[i]=$gpf
done
IPv6P=`echo "${pg[0]}:${pg[1]}:${pg[2]}:${pg[3]}/$IPv6L"`
IPv6_address
echo "$IPv6P"	
}

cut_group()
{
g_prefix=`echo $groupa_prefix|awk '{print substr($groupa_prefix,1,gl)}' gl=$IPv6L`
#orandom1=`echo "obase=16; ibase=2; $random1"|bc`
gL=`expr 64 - $IPv6L`
while [ "$gL" -gt "0" ]; do
	g_prefix=$g_prefix"0"
	gL=`expr $gL - 1`
done
g_change
}

#对IPv4前缀进行修改
agroup()
{
cut_IPv4P
range
case $group in
	1 | 2) 
		a=(0 1)
		b=`for ((gi=0;gi<32;gi++)); do echo -n ${a[$RANDOM % ${#a[*]}]}; done`
		groupa_prefix=`echo "$i1$i2$b$i3$i4"`
		cut_group;;
	3) 
		groupa_prefix=`echo "$i1$i2$i3$i4"`
		groupa_prefix=`echo $groupa_prefix |sed 's/./&0/g'`
		cut_group;;
	4)
		groupa_prefix=`echo "$i1$i1$i2$i2$i3$i3$i4$i4"`
		cut_group;;
	*) echo "****目前还没有实现5,6,7****";;
esac
}

#自己输入IPv4前缀，转换和按规则输出
fagroup()
{
read_IPv4P
agroup
save_date_to_file
if [ "$IPv6_Prefix_Btable" != "no" ]; then
	echo "$IPv6P" >> $IPv6_Prefix_Btable	
fi
}

#从文件读IPv4前缀，转换和按规则输出
ffgroup()
{
IPv4Pff
save_date_to_file
for((f_j=1;f_j<=$inumber;f_j++));do
	IPv4P=`awk '{if (NR==f_m) print $1}' f_m=$f_j $ffilename`
	cut_IPv4P
	agroup
	if [ "$IPv6_Prefix_Btable" != "no" ]; then
		echo "$IPv6P" >> $IPv6_Prefix_Btable	
	fi
done
}

#从文件读还是自己输入
groupAa()
{
	if [ "$hao" = "-fa" ]; then
		fagroup		
	fi
	if [ "$hao" = "-ff" ]; then
		ffgroup
	fi
}

#选择A组策略的组号
groupA()
{
echo "GroupA"
echo "策略A分为7组，A1,A2,A3,A4,A5,A6,A7"
echo "请选择第几种策略，输入对应的策略号就好了"
echo "A1,A2在IPv4前缀中间随机插入"
echo "A3在IPv4bit后面插入0或1"
echo "A4重复IPv4前缀每一个byte"
echo "A5重复IPv4前缀每一个bit"
echo "A6在每一个IPv4bit前加0"
echo "A7在每一个IPv4bit前加1"
read group

case $group in
	1 |2 | 3 |4 |5 |6 |7)
	   groupAa;;
	*) echo "错误的组号，请重新输入:"
	   groupAa;;
esac
}

#执行A组策略
if [ "$2" = "-A" ]; then
	hao=$1
	groupA
fi
#退出
exit 0
